package com.sailfish.springbootdemo.service.db2.impl;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.sailfish.springbootdemo.pojo.Result;
import com.sailfish.springbootdemo.service.db2.S3UploadFileService;
import com.sailfish.springbootdemo.utils.CommonUtils;
import com.sailfish.springbootdemo.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Service
public class S3UploadFileServiceImpl implements S3UploadFileService {

    @Autowired
    private AmazonS3 amazonS3;

    @Value("${personal.config.amazon-s3.url}")
    private String url;

    @Value("${personal.config.amazon-s3.file-bucket}")
    private String fileBucket;

    @Override
    public String uploadFile(String directory, MultipartFile uploadFile) {
        String filename = uploadFile.getOriginalFilename();
        try {
            //将MultipartFile转成File
            File file = File.createTempFile("temp", ".temp");
            InputStream inputStream = uploadFile.getInputStream();
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            inputStream.close();
            System.out.println("将MultipartFile转成File成功");

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType("application/octet-stream");
            PutObjectResult result = amazonS3.putObject(new PutObjectRequest(fileBucket,
                    directory + "/" + filename, new FileInputStream(file), metadata)
                    //配置访问权限
                    .withCannedAcl(CannedAccessControlList.PublicRead));
            String address = directory + "/" + filename;
            return address;
        } catch (Exception e) {
            System.out.println(String.format("上传文件【%s】到AmazonS3失败:", filename) + e.getMessage());
            return null;
        }

    }


    @Override
    public String uploadFile2(String directory, File uploadFile) {
        String filename = uploadFile.getName(); // 直接获取文件名
        try (FileInputStream fileInputStream = new FileInputStream(uploadFile)) {
            // 1. 配置S3对象元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType("application/octet-stream");
            metadata.setContentLength(uploadFile.length());

            // 2. 构建S3上传请求
            PutObjectRequest putRequest = new PutObjectRequest(
                    fileBucket,
                    directory + "/" + filename,
                    fileInputStream,
                    metadata
            ).withCannedAcl(CannedAccessControlList.PublicRead); // 公共读权限

            // 3. 执行上传
            amazonS3.putObject(putRequest);
            return directory + "/" + filename; // 返回存储路径
        } catch (Exception e) {
            System.err.println("上传文件【" + filename + "】失败: " + e.getMessage());
            return null;
        }
    }



    @Value("${personal.config.env}")
    private String env;

    @Override
    public String getImageBase64FromUrl(String imageUrl) {
        String base64Image = null;
        try {
            imageUrl = imageUrl.replaceAll("\\\\", "/");
            URI uri = new URI(imageUrl);
            String encodedUrl = uri.toASCIIString();
            //System.out.println(encodedUrl);
            byte[] imageBytes = getImageDataFromUrl(encodedUrl);
            if (imageBytes != null && imageBytes.length > 0) {
                base64Image = Base64.getEncoder().encodeToString(imageBytes);
                //System.out.println("Base64 encoded image:\n" + base64Image);
            } else {
                System.err.println("Failed to retrieve the image data.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64Image;
    }

    public byte[] getImageDataFromUrl(String urlStr) throws IOException {
        if (env.equals("dev")) {
            urlStr = "http://192.168.31.228:8890/capacityFiles/" + urlStr;
        }
        try (InputStream inputStream = new URL(urlStr).openStream()) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            int bytesRead;
            byte[] buffer = new byte[1024];

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String getImageBase64FromUrl2(String imageUrl, HttpServletRequest request) {
        String base64Image = null;
        try {
            imageUrl = imageUrl.replaceAll("\\\\", "/");
            URI uri = new URI(imageUrl);
            String encodedUrl = uri.toASCIIString();
            //System.out.println(encodedUrl);
            byte[] imageBytes = getImageDataFromUrl2(encodedUrl,request);
            if (imageBytes != null && imageBytes.length > 0) {
                base64Image = Base64.getEncoder().encodeToString(imageBytes);
                //System.out.println("Base64 encoded image:\n" + base64Image);
            } else {
                System.err.println("Failed to retrieve the image data.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64Image;
    }

    public byte[] getImageDataFromUrl2(String urlStr, HttpServletRequest request) throws IOException {
        if (env.equals("dev")) {
            urlStr = CommonUtils.getApiPrefixUrl(request)+"/capacityFiles/" + urlStr;
        }
        try (InputStream inputStream = new URL(urlStr).openStream()) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            int bytesRead;
            byte[] buffer = new byte[1024];

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public Result downloadS3FileToBase64(String s3Url, String newFileName) {
        try{
            Map<String, Object> map = new HashMap<>();
            map.put("fileName", newFileName);
            if(s3Url != null && !"".equals(s3Url)){
                // 1. 下载 Excel 文件并保存到临时文件
                URL url = new URL(s3Url);
                InputStream in = url.openStream();
                Path tempFile = Files.createTempFile("temp-excel-", ".xlsx");
                Files.copy(in, tempFile, StandardCopyOption.REPLACE_EXISTING);
                in.close();
                // 2. 将文件读取为字节数组
                byte[] fileBytes = Files.readAllBytes(tempFile);
                // 3. 将字节数组转换为 Base64 字符串
                String base64String = Base64.getEncoder().encodeToString(fileBytes);
                // 4. 打印或使用 Base64 字符串
                // 可选步骤：删除临时文件
                Files.deleteIfExists(tempFile);
                map.put("base64", base64String);
                return ResultUtil.success(map);
            }else{
                return ResultUtil.error(500, "s3链接不存在", "s3 url not exist", null);
            }
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.error(500, e.getMessage(), e.getMessage(), null);
        }
    }
}
